
package general.art;

import general.database.SQLiteInterface;
import general.database.info.LinkInfo;
import general.exceptions.NodeNotFoundException;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
* This class implements the link object between two nodes and the
* associated weight for this link. Both the server and the back-end 
* tool should use this class.  
* 
* @author - Lance, Hood
* 
* @param <A>     The type of the first linked node.
* @param <B>     The type of the second linked node.
* 
*/
public class Link {

	private static Map<Integer, Link> SET_OF_ALL_LINKS = new HashMap<Integer, Link>(); 
	
	//private static Set<Link> SET_OF_ALL_LINKS = new HashSet<Link>();
	
	public static List<Link> FIND_LINKS_FROM_NODE(int nodeKey) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException, NodeNotFoundException{
	
			List<Link> newLinks = new LinkedList<Link>();
			
			
			SQLiteInterface dataBaseInterface = new SQLiteInterface();
			
			for(LinkInfo l : dataBaseInterface.getLinkInfo(nodeKey)){

				newLinks.add(FIND_LINK(l));
			}
		
		return newLinks;
		
	}
	
	
	private static Link FIND_LINK(LinkInfo linkInfo) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException, NodeNotFoundException{
		
		if(!SET_OF_ALL_LINKS.containsKey(linkInfo.key)){
		
			SET_OF_ALL_LINKS.put(linkInfo.key, new Link(linkInfo));
		
	    }
		
		return SET_OF_ALL_LINKS.get(linkInfo.key);
		
	}
	
	
    /**
     * Holds the first node in the link.
     */
    private int mKey;
    
     /**
     * Holds the first node in the link.
     */
    private Node mNode1;

    /**
     * Holds the second node in the link.
     */
    private Node mNode2;
    
    /**
     * Holds the second node in the link.
     */
    private double mWeight;

     
    /**
     * Link constructor takes two nodes and a weight. The weight should
     * be a double in the range of zero to one. The closer the weight to
     * one the stronger is the link and vice versa.  
     * 
     * @param node1 - first node to link
     * @param node2 - second node to link
     * @param weight - weight of the link 
     * @param key    - the key of the link.
     *    private Link(final int key , final A node1, final B node2, final double weight) {
        this.mNode1 = node1;
        this.mNode2 = node2;
        this.mWeight = weight;
        this.mKey = key;
    }
    /**
     * @throws NodeNotFoundException 
     * @throws SQLException 
     * @throws ClassNotFoundException 
     * @throws IllegalAccessException 
     * @throws InstantiationException 
     */   
    private Link(LinkInfo l) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException, NodeNotFoundException{
    	
    	mNode1 = Node.FIND_NODE(l.node1);
    	mNode2 = Node.FIND_NODE(l.node2);
    	mWeight = 1.0;
    	mKey = l.key;
    	
    }
    
    
    /**
     * @return - Returns the Key for the link.
     */
    public int getKey() {
        return mKey;
    }
     
   /**
    * @return - Returns the first node in this link.
    */
    public Node getNode1() {
        return mNode1;
    }

   /**
    * @return - Returns the second node in this link.
    */
    public Node getNode2() {
        return mNode2;
    }

   /**
    * @return - Returns the weight of this link.
    */
    public double getWeight() {
        return mWeight;
    }
    

}
